#ifndef BREAKINGBUF_H_INCLUDED__
#define BREAKINGBUF_H_INCLUDED__

#include <streambuf>

template <class charT, class traits = std::char_traits<charT> >
class basic_breaking_buf : public std::basic_streambuf<charT, traits>
{
    typedef charT char_type;
    typedef typename traits::int_type int_type;
    typedef typename traits::pos_type pos_type;
    typedef typename traits::off_type off_type;
    typedef traits traits_type;
    typedef std::basic_streambuf<charT, traits> streambuf_type;

protected:
	enum { BREAK_SIZE = 10 };
	char_type buffer_[BREAK_SIZE];
	static const char_type delim_ = '\n';
	streambuf_type* dest_;

public:
    /**
	 * Constructor initializes the data buffer.
	 * One character less to let the BUFFER_SIZEth character
	 * cause a call to overflow(). 
     */
    basic_breaking_buf(streambuf_type* dst) : dest_(dst)
	{
        setp(buffer_, buffer_ + (BREAK_SIZE - 1));
    }

    virtual ~basic_breaking_buf()
	{
        sync();
    }

protected:
    int flushBuffer ()
	{
        int num = pptr() - pbase();
		dest_->sputn(&buffer_[0], num);
		dest_->sputc(delim_);
        pbump(-num); // reset put pointer accordingly
        return num;
    }

    /** Buffer full, write c and all previous characters. */
    virtual int_type overflow (int_type c)
	{
        if (c != EOF)
		{
            *pptr() = c;
            pbump(1);
        }

        if (flushBuffer() == EOF)
		{
            return EOF;
        }
        return c;
    }

    virtual int sync ()
	{
        if (flushBuffer() == EOF)
		{
            return -1;
        }
        return 0;
    }
};

typedef basic_breaking_buf<char> breaking_buf;
typedef basic_breaking_buf<wchar_t> wbreaking_buf;

#endif
